package br.com.vti.sisp_sicrim.antigo.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.ParseException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.swing.text.MaskFormatter;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporter;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.export.JRPdfExporter;

import org.apache.commons.lang3.StringUtils;

import br.com.caelum.vraptor.interceptor.download.InputStreamDownload;

public class Relatorios {

	private int pagesize = 60;
	private int linesize = 80;
	private int pagenumber = 1;
	private int pageline = 1;
	private int idRel = 0;
	private String tpLinRel;
	private RelatorioConfig relConfig;
	ReportDesigner reportDesigner = new ReportDesigner();
	JasperDesign design;
	JasperReport jr;
	List<RelatorioConfig> report;
	List<LinhasRel> linhasRelatorio;
	JRBeanCollectionDataSource jrBean;
	Map<String, Object> parametros;
	JasperPrint impressao;

	public Relatorios() throws JRException {

		report = new LinkedList<RelatorioConfig>();
		// preparar layout e conte�do
		design = reportDesigner.getDesign(this.pagesize);
		jr = JasperCompileManager.compileReport(design);
		linhasRelatorio = new LinkedList<LinhasRel>();
		parametros = new HashMap<String, Object>();
		// Arrays.fill(qtdcam, 0);
		pagenumber = 1;
		pageline = 1;
	}

	public void setNumeroRel(int idRel, String tpLinRel) {
		this.idRel = idRel;
		this.tpLinRel = tpLinRel;
	}

	public void setNumeroLinhaRel(int nroLinha, int qtdCampos) {
		relConfig = new RelatorioConfig(qtdCampos);
		relConfig.setNumeroRel(this.idRel);
		relConfig.setNumeroLinhaRel(nroLinha);
		relConfig.setTpLinRel(this.tpLinRel);
		// report.add(relConfig);
	}

	public void setFimLinhaRel() {
		report.add(relConfig);
	}

	public void adicionaCampo(int coluna, int tamanho, String campo, String tipo, String mascara, String titulo) {

		relConfig.qtdcam++;
		relConfig.coluna[relConfig.qtdcam] = coluna;
		relConfig.tamanho[relConfig.qtdcam] = tamanho;
		relConfig.campo[relConfig.qtdcam] = campo;
		relConfig.tipo[relConfig.qtdcam] = tipo;
		relConfig.mascara[relConfig.qtdcam] = mascara;
		relConfig.titulo[relConfig.qtdcam] = titulo;
	}

	public int localizaCampo(RelatorioConfig repConf, int nroRel, String campo) {
		int index = -1;
		// RelatorioConfig repConf;
		// for (int iRel = 0; iRel < report.size(); iRel++) {
		// repConf = report.get(iRel);
		if (nroRel != repConf.idRel)
			return -1;
		for (int ind = 1; ind <= repConf.qtdcam; ind++) {
			if (repConf.campo[ind].toUpperCase().equals(campo.toUpperCase()))
				return ind;
		}
		// }
		return index;
	}

	public void adicionaValorReport(String campo, Object valor) throws ParseException {
		int nroRel, nroCam;
		RelatorioConfig repConf;
		for (nroRel = 0; nroRel < report.size(); nroRel++) {
			repConf = report.get(nroRel);
			nroCam = localizaCampo(repConf, repConf.idRel, campo);
			if (nroCam != -1) {
				adicionaValor(nroRel, campo, valor);
			}

		}
	}

	public void adicionaValor(int nroRel, String campo, Object valor) throws ParseException {

		int index;
		String strVal;
		RelatorioConfig repConf;
		for (int iRel = 0; iRel < report.size(); iRel++) {
			repConf = report.get(iRel);
			// if (nroRel != repConf.idRel)
			// continue;
			index = localizaCampo(repConf, repConf.idRel, campo);
			if (index == -1)
				continue;
			switch (repConf.tipo[index]) {
			case "A":
			case "X": {
				strVal = String.valueOf(valor);
				if (!repConf.mascara[index].equals("")) {
					MaskFormatter mask = new MaskFormatter(repConf.mascara[index]);
					try {
						strVal = mask.valueToString(strVal);
					} catch (Exception e) {

					}

				} else {
					while (strVal.length() < repConf.tamanho[index])
						strVal = strVal + " ";
					try {
						strVal = strVal.substring(0, repConf.tamanho[index]);
					} catch (Exception e) {

					}
				}
				repConf.valor[index] = strVal;
				break;
			}
			case "N":
			case "L": {
				strVal = String.valueOf(valor);
				if (!repConf.mascara[index].equals("")) {
					MaskFormatter mask = new MaskFormatter(repConf.mascara[index]);
					try {
						strVal = mask.valueToString(strVal);
					} catch (Exception e) {

					}
				} else {
					while (strVal.length() < repConf.tamanho[index])
						strVal = " " + strVal;
					strVal = strVal.substring(0, repConf.tamanho[index]);
				}
				repConf.valor[index] = strVal;
				break;
			}
			default: {
				strVal = String.valueOf(valor);
				while (strVal.length() < repConf.tamanho[index])
					strVal = strVal + " ";
				strVal = strVal.substring(0, repConf.tamanho[index]);
				repConf.valor[index] = strVal;
				break;
			}
			}
		}
	}

	public void saltaLinhas(int qtdLinhas) throws ParseException, JRException {
		for (int i = 1; i <= qtdLinhas; i++) {
			linhasRelatorio.add(new LinhasRel(""));
			pageline++;
		}
	}

	public void gravaRelatorio(Relatorios relat, int nroRel, boolean gravandoCabecalho) throws ParseException, JRException {

		int ind, iCab, nCab;
		String linhaRel = "";
		RelatorioConfig repConf, repAux;
		relat.adicionaValorReport("nroPagina", String.valueOf(pagenumber));
		for (int iRel = 0; iRel < report.size(); iRel++) {
			repConf = report.get(iRel);
			if (pageline == 1 && !gravandoCabecalho) {
				// GRAVAR CABECALHO

				nCab = 0;
				for (iCab = 0; iCab < report.size(); iCab++) {
					repAux = report.get(iCab);
					if (repAux.tpLinRel.equals("C") && repAux.idRel != nCab) {
						gravaRelatorio(relat, repAux.idRel, true);
						nCab = repAux.idRel;
					}
				}

			}
			if (nroRel != repConf.idRel)
				continue;
			while (pageline < repConf.nroLinha) {
				linhasRelatorio.add(new LinhasRel(""));
				pageline++;
			}

			linhaRel = StringUtils.repeat(" ", linesize + 1);
			for (ind = 1; ind <= repConf.qtdcam; ind++) {
				if (repConf.titulo[ind].equals("")) {
					linhaRel = UtilBean.moveSubstring(linhaRel, repConf.coluna[ind] - 1, repConf.tamanho[ind], repConf.tipo[ind], repConf.valor[ind]);
				} else {
					linhaRel = UtilBean.moveSubstring(linhaRel, repConf.coluna[ind] - 1, repConf.tamanho[ind], "A", repConf.titulo[ind]);
				}
			}
			if (linhaRel.trim().equals("-")) {
				linhaRel = StringUtils.repeat("-", this.linesize);
			}
			linhasRelatorio.add(new LinhasRel(linhaRel));
			if (pageline >= pagesize) {
				pageline = 1;
				pagenumber++;
			} else {
				pageline++;
			}
		}
	}

	public void setPageSize(int pagesize) throws JRException {
		this.pagesize = pagesize;
		design = reportDesigner.getDesign(this.pagesize);
		jr = JasperCompileManager.compileReport(design);
	}

	public void setLineSize(int linesize) {
		this.linesize = linesize;
	}

	public int getPageNumber() {
		return pagenumber;
	}

	public int getPageLine() {
		return pageline;
	}

	public void setPageLine(int pageline) {
		this.pageline = pageline;
	}

	public int getPageSize() {
		return pagesize;
	}

	public String imprimir1() throws JRException, FileNotFoundException {
		String nomearq = "";
		jrBean = new JRBeanCollectionDataSource(linhasRelatorio);
		impressao = JasperFillManager.fillReport(jr, parametros, jrBean);
		nomearq = System.currentTimeMillis() + ".pdf";
		OutputStream outputStream = new FileOutputStream(UtilBean.pathFiles() + nomearq);
		JRPdfExporter exporter = new JRPdfExporter();
		exporter.setParameter(JRExporterParameter.JASPER_PRINT, impressao);
		exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputStream);
		exporter.exportReport();
		try {
			outputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return nomearq;
	}

	public InputStreamDownload imprimir() {
		try {

			JasperReport jr = JasperCompileManager.compileReport(design);

			// preparar layout e conte�do
			JRBeanCollectionDataSource jrBean = new JRBeanCollectionDataSource(linhasRelatorio);
			Map<String, Object> parametros = new HashMap<String, Object>();
			JasperPrint impressao = JasperFillManager.fillReport(jr, parametros, jrBean);

			byte[] bytes = null;

			try {
				ByteArrayOutputStream exported = new ByteArrayOutputStream();
				JRExporter exporter = new JRPdfExporter();

				exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, exported);
				exporter.setParameter(JRExporterParameter.JASPER_PRINT, impressao);
				exporter.exportReport();

				bytes = exported.toByteArray();

			} catch (Exception e) {
				e.printStackTrace();
				return null;
			}

			return new InputStreamDownload(new ByteArrayInputStream(bytes), "application/download", System.currentTimeMillis() + ".pdf", true, bytes.length);

		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}

}
